ERC884 DGCL compatible share token
https://gyazo.com/5240568a9e687537a302951972c3fb46
これは何?
ERC884というアメリカのデラウェア州法で定められたDGCL(Delaware General Corporations Law)に則った株式トークンの標準規格の提案について解説した記事です。
動機
弁護士先生からERC884の内容の質問を受け、テック方面からの理解をしておきたいという思い。
日本国内でERC884が参考になるかどうかはわからないが、知ってる分には損はないのかなという気持ち。
簡単にまとめると
アメリカのデラウェア州ではブロックチェーン(分散台帳技術)を用いて企業の株式の管理を行うことが合法となった(認められた)。2017年に法案が可決。
法案は可決されたものの、実際の採用には至っておらず、現在は可決された法案の内容に則ってEthereumブロックチェーンに展開されたスマートコントラクトを用いてどのように株式所有を管理方法に関する標準規格の検討が進んでいるという状況。
法律に則った株式所有管理の標準規格がERC884として2018年2月に提案されており、2018年12月時点ではDraftのステータス。PoCなども行われているので今後に期待
ERC884ってなに?
ERC884とは、トークン規格の提案。USのデラウェア州が可決した「ブロックチェーン上に企業株式の管理を行うことを許可する法案」の内容に則り、Ethereumブロックチェーン上で展開されるスマートコントラクト上で、上記の法案内容を実現するために必要な実装の標準規格が提案されている。ERC884はERC20と下方互換性があり、ERC884独自の機能をERC20トークンコントラクトにいくつか盛り込んでいるというのが規格の概要。
株式の発行/管理にブロックチェーン及びERC884を用いることにより、来の株式発行手続きの簡略化が行えることが期待されており、結果的に従来よりも労働時間と金銭コストの削減ができると考えられている。(具体的な数字ベースでの期待値などはなく、あくまで推定)
デラウェア州法ってなに?
デラウェア州ってどこやねんという感じでイメージが湧かない方はこちらを参考に。(USでは2番目に面積が小さい州らしい) 聞いた感じだとデラウェア州って会社設立しやすいそうな(税とか安い)
USでは州ごとに法律が定められている。例えば、車の運転に際しドライバーライセンスが必要になるが、ワシントン州では日本の免許と適正検査(視力検査など)を行えば簡単にライセンスを取得することができる。が、全ての州でこれが行える訳ではない。各州ごとにドライバーライセンスの取得方法などが異なっていたりする。
ドライバーラインセンスに限らず、法律の違いは全てに存在しており(もちろん同じものもある)、ERC884で注目しているのはデラウェア州の法律。
ロイターの記事でデラウェア州の法案について紹介されている。
CoinDeskでも。
デラウェア州議会で可決された内容。
ERC884で提案されている標準規格の詳細
PoCが行われていたりする
EIP884
具体的な内容として提案されているもの
1. 株式トークンコントラクトのdecimalsは0を設定する。ERC884では1トークン = 1株式と表現し、トークンは分割不可能なものとして存在するため。
株式トークンの操作(transferなど)はWhitelist登録を行われたユーザーにのみが可能のとする
2. ERC884ではcancelAndReissueを実装し、古いEthereumアドレスを新しいEthereumアドレスに置き換え、古いアドレスを使用不可にする
自身が保有する株式トークンを全てtransferし、保有が0になった場合、株主名簿からホルダー名を削除する
3. アイデンティティハッシュを用いて、個人を特定する
The Act(デラウェア州が定めた法律)を遵守するためには、全ての株主名と、現実の住所を管理する必要がある。これらの情報(株主名/住所)をパブリックなブロックチェーン上で管理するのは、プライバシーの観点で見た場合望ましくない。
対してERC884では、トークンコントラクトのストレージ変数に情報のハッシュ値(任意の文字列データ)を格納する仕組みを採用するのが良いと考えられている
所有者の名前 / 現実の住所 / 所有者のEthereumアドレス を格納するオフチェーンストレージ(RDB / file storage / etc...)を用意し、保存する。保存した3つのデータをインプットとしハッシュ化。ハッシュ化された値をコントラクトのストレージに格納する。ハッシュを元に保存データの正当性を検証する。検証にはhasHash関数を利用する
具体的な実装は各々の開発者に任されているが、GET https://<host>/<pathPrefix>/:ethereumAddress -> [true|false] のようなAPIエンドポイントにGETリクエストすることで確認できるのが理想。
前提としてWhitelist登録とCrowdsaleを行う前提で話が行われているため、mint/burnは別途拡張する必要がある
ERC20に準拠
code:javascript
contract ERC20 {
function totalSupply() public view returns (uint256);
function balanceOf(address who) public view returns (uint256);
function transfer(address to, uint256 value) public returns (bool);
function allowance(address owner, address spender) public view returns (uint256);
function transferFrom(address from, address to, uint256 value) public returns (bool);
function approve(address spender, uint256 value) public returns (bool);
event Approval(address indexed owner, address indexed spender, uint256 value);
event Transfer(address indexed from, address indexed to, uint256 value);
}
ERC884の規格
code:javascript
contract ERC884 is ERC20 {
/**
* This event is emitted when a verified address and associated identity hash are
* added to the contract.
* @param addr The address that was added.
* @param hash The identity hash associated with the address.
* @param sender The address that caused the address to be added.
*/
event VerifiedAddressAdded(
address indexed addr,
bytes32 hash,
address indexed sender
);
/**
* This event is emitted when a verified address and associated identity hash are
* removed from the contract.
* @param addr The address that was removed.
* @param sender The address that caused the address to be removed.
*/
event VerifiedAddressRemoved(address indexed addr, address indexed sender);
/**
* This event is emitted when the identity hash associated with a verified address is updated.
* @param addr The address whose hash was updated.
* @param oldHash The identity hash that was associated with the address.
* @param hash The hash now associated with the address.
* @param sender The address that caused the hash to be updated.
*/
event VerifiedAddressUpdated(
address indexed addr,
bytes32 oldHash,
bytes32 hash,
address indexed sender
);
/**
* This event is emitted when an address is cancelled and replaced with
* a new address. This happens in the case where a shareholder has
* lost access to their original address and needs to have their share
* reissued to a new address. This is the equivalent of issuing replacement
* share certificates.
* @param original The address being superseded.
* @param replacement The new address.
* @param sender The address that caused the address to be superseded.
*/
event VerifiedAddressSuperseded(
address indexed original,
address indexed replacement,
address indexed sender
);
/**
* Add a verified address, along with an associated verification hash to the contract.
* Upon successful addition of a verified address, the contract must emit
* VerifiedAddressAdded(addr, hash, msg.sender).
* It MUST throw if the supplied address or hash are zero, or if the address has already been supplied.
* @param addr The address of the person represented by the supplied hash.
* @param hash A cryptographic hash of the address holder's verified information.
*/
function addVerified(address addr, bytes32 hash) public;
/**
* Remove a verified address, and the associated verification hash. If the address is
* unknown to the contract then this does nothing. If the address is successfully removed, this
* function must emit VerifiedAddressRemoved(addr, msg.sender).
* It MUST throw if an attempt is made to remove a verifiedAddress that owns tokens.
* @param addr The verified address to be removed.
*/
function removeVerified(address addr) public;
/**
* Update the hash for a verified address known to the contract.
* Upon successful update of a verified address the contract must emit
* VerifiedAddressUpdated(addr, oldHash, hash, msg.sender).
* If the hash is the same as the value already stored then
* no VerifiedAddressUpdated event is to be emitted.
* It MUST throw if the hash is zero, or if the address is unverified.
* @param addr The verified address of the person represented by the supplied hash.
* @param hash A new cryptographic hash of the address holder's updated verified information.
*/
function updateVerified(address addr, bytes32 hash) public;
/**
* Cancel the original address and reissue the tokens to the replacement address.
* Access to this function MUST be strictly controlled.
* The original address MUST be removed from the set of verified addresses.
* Throw if the original address supplied is not a shareholder.
* Throw if the replacement address is not a verified address.
* Throw if the replacement address already holds tokens.
* This function MUST emit the VerifiedAddressSuperseded event.
* @param original The address to be superseded. This address MUST NOT be reused.
*/
function cancelAndReissue(address original, address replacement) public;
/**
* The transfer function MUST NOT allow transfers to addresses that
* have not been verified and added to the contract.
* If the to address is not currently a shareholder then it MUST become one.
* If the transfer will reduce msg.sender's balance to 0 then that address
* MUST be removed from the list of shareholders.
*/
function transfer(address to, uint256 value) public returns (bool);
/**
* The transferFrom function MUST NOT allow transfers to addresses that
* have not been verified and added to the contract.
* If the to address is not currently a shareholder then it MUST become one.
* If the transfer will reduce from's balance to 0 then that address
* MUST be removed from the list of shareholders.
*/
function transferFrom(address from, address to, uint256 value) public returns (bool);
/**
* Tests that the supplied address is known to the contract.
* @param addr The address to test.
* @return true if the address is known to the contract.
*/
function isVerified(address addr) public view returns (bool);
/**
* Checks to see if the supplied address is a shareholder.
* @param addr The address to check.
* @return true if the supplied address owns a token.
*/
function isHolder(address addr) public view returns (bool);
/**
* Checks that the supplied hash is associated with the given address.
* @param addr The address to test.
* @param hash The hash to test.
* @return true if the hash matches the one supplied with the address in addVerified, or updateVerified.
*/
function hasHash(address addr, bytes32 hash) public view returns (bool);
/**
* The number of addresses that hold tokens.
* @return the number of unique addresses that hold tokens.
*/
function holderCount() public view returns (uint);
/**
* By counting the number of token holders using holderCount
* you can retrieve the complete list of token holders, one at a time.
* It MUST throw if index >= holderCount().
* @param index The zero-based index of the holder.
* @return the address of the token holder with the given index.
*/
function holderAt(uint256 index) public view returns (address);
/**
* Checks to see if the supplied address was superseded.
* @param addr The address to check.
* @return true if the supplied address was superseded by another address.
*/
function isSuperseded(address addr) public view returns (bool);
/**
* Gets the most recent address, given a superseded one.
* Addresses may be superseded multiple times, so this function needs to
* follow the chain of addresses until it reaches the final, verified address.
* @param addr The superseded address.
* @return the verified address that ultimately holds the share.
*/
function getCurrentFor(address addr) public view returns (address);
}
感想
ERC884の株式トークンを取引できるかどうかを別として、着実に1歩ずつブロックチェーン技術を社会に適用するために動いているのは非常に好感が持てた。
汎用的なSTの規格はERC1400やDS-Protocolなどで提案されているが、州ごとに法律が異なるため、最終的には各州の法律に準拠した各々のトークンスタンダートが生まれるのではないのかなという推察。
日本でも同じで、日本とUSはの法律にも違いがあるため、ERC1400に準拠するけども、独自のルール適用などになるのかなと。
yamarkz.icon < おお! やはりそんなイキフン
トークンスタンダートとして採用されるかどうかは、実利用の実績と汎用性があり、他の事例に活用できると認められた時に採用されるという理解。
参考資料
Q&A
mosa_siru.icon < 2017年ってすごいなデラウェア州…!
moonty_sal.icon < それ
peroyuki.icon < 日本人も買えるのかな
peroyuki.icon < あと「株式発行手続の簡素化」が中心だから、売買時の価格の交渉とかは流石に今までどおりオフラインでごにょごにょ?
mosa_siru.icon < どうも、クリアリングは結局既存の仕組み(原本管理)っぽい
mosa_siru.icon < Mariane「おそらく上限5%ルールを毎日必死に各証券会社が計算してるところが楽になる」
mosa_siru.icon < yamarkz「結局まだPoC段階なのでふーんってかんじ」